#include "libcomm.h"

// returns the initial value.
int Atom::Exchange(volatile int& target, int val)
{
	int initialValue;
#ifdef COMM_MSVC
	initialValue = InterlockedExchange((volatile long*)&target,val);
#else
	initialValue = __sync_lock_test_and_set(&target,val);
#endif
	return initialValue;
}

int Atom::CompareExchange(volatile int& target, int val, int valcompare)
{
	int initialValue;
#ifdef COMM_MSVC
	initialValue = InterlockedCompareExchange((volatile long*)&target,val,valcompare);
#else
	initialValue = __sync_val_compare_and_swap(&target,valcompare,val);
#endif
	return initialValue;
}

void* Atom::ExchangePointer(void* volatile& target, void* val)
{
	void* initialValue;
#ifdef COMM_MSVC
	initialValue = InterlockedExchangePointer(&target,val);
#else
	initialValue = __sync_lock_test_and_set(&target, val); 
#endif
	return initialValue;
}

void* Atom::CompareExchangePointer(void* volatile& target, void* val, void* valcompare)
{
	void* initialValue;
#ifdef COMM_MSVC
	initialValue = InterlockedCompareExchangePointer(&target,val,valcompare);
#else
	initialValue = __sync_val_compare_and_swap(&target,valcompare,val); 
#endif
	return initialValue;
}

// returns the initial value.
int Atom::Add(volatile int& target, int val)
{
	int initialValue;
#ifdef COMM_MSVC
	initialValue = InterlockedExchangeAdd((volatile long*)&target,val);
#else
	initialValue = __sync_fetch_and_add(&target,val);
#endif
	return initialValue;
}

// returns the initial value.
int Atom::Sub(volatile int& target, int val)
{
	int initialValue;
#ifdef COMM_MSVC
	initialValue = InterlockedExchangeAdd((volatile long*)&target,-val);
#else
	initialValue = __sync_fetch_and_sub(&target,val);
#endif
	return initialValue;
}

// returns the initial value.
long long Atom::Exchange(volatile long long& target, long long val)
{
	long long initialValue;
#ifdef COMM_MSVC
	initialValue = InterlockedExchange64(&target,val);
#else
	initialValue = __sync_lock_test_and_set(&target,val);
#endif
	return initialValue;
}

long long Atom::CompareExchange(volatile long long& target, long long val, long long valcompare)
{
	long long initialValue;
#ifdef COMM_MSVC
	initialValue = InterlockedCompareExchange64(&target,val,valcompare);
#else
	initialValue = __sync_val_compare_and_swap(&target,valcompare,val);
#endif
	return initialValue;
}

// returns the initial value.
long long Atom::Add(volatile long long& target, long long val)
{
	long long initialValue;
#ifdef COMM_MSVC
	initialValue = InterlockedExchangeAdd64(&target,val);
#else
	initialValue = __sync_fetch_and_add(&target,val);
#endif
	return initialValue;
}

// returns the initial value.
long long Atom::Sub(volatile long long& target, long long val)
{
	long long initialValue;
#ifdef COMM_MSVC
	initialValue = InterlockedExchangeAdd64(&target,-val);
#else
	initialValue = __sync_fetch_and_sub(&target,val);
#endif
	return initialValue;
}

